/*
 * Copyright (c) 2015 Sfkj Science And Technology Co.,Ltd.
 * All Rights Reserved.
 * This software is the confidential and proprietary information of
 * Sfkj Science And Technology Co.,Ltd.
 * ("Confidential Information").You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sfkj.
 */
package com.sfkj.walk.axon.interceptors;

import com.google.common.base.MoreObjects;
import com.google.common.collect.Maps;
import com.sfkj.walk.security.SpringSecurityHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.axonframework.eventhandling.MetaDataConstants;
import org.axonframework.messaging.Message;
import org.axonframework.messaging.MessageDispatchInterceptor;
import org.axonframework.messaging.MetaData;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;

@Slf4j
public class RequestHeaderInterceptor<T extends Message<?>> implements MessageDispatchInterceptor<T> {

    @Override
    public BiFunction<Integer, T, T> handle(List<T> messages) {
        HttpServletRequest request = getRequest();

        return (Integer index, T message) -> {
            Map<String, Object> items = Maps.newHashMap();
            items.put(MetaDataConstants.CURRENT_USER_ID, SpringSecurityHelper.getUserId());

            if (Objects.nonNull(request)) {
                items.put(MetaDataConstants.USER_AGENT, MoreObjects.firstNonNull(request.getHeader(MetaDataConstants.USER_AGENT), StringUtils.EMPTY));
                items.put(MetaDataConstants.HOST, MoreObjects.firstNonNull(request.getRemoteHost(), StringUtils.EMPTY));
                items.put(MetaDataConstants.PORT, MoreObjects.firstNonNull(request.getRemotePort(), StringUtils.EMPTY));
            }

            items.put(MetaDataConstants.COMMAND_ID, message.getIdentifier());

            message = (T) message.withMetaData(MetaData.from(items).mergedWith(message.getMetaData()));

            return message;
        };
    }

    private HttpServletRequest getRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return requestAttributes == null ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
    }
}
